home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / sndhrdw / williams.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  40KB  |  1,427 lines

  1. /***************************************************************************
  2.  
  3.     Midway/Williams Audio Board
  4.     ---------------------------
  5.  
  6.     6809 MEMORY MAP
  7.  
  8.     Function                                  Address     R/W  Data
  9.     ---------------------------------------------------------------
  10.     Program RAM                               0000-07FF   R/W  D0-D7
  11.  
  12.     Music (YM-2151)                           2000-2001   R/W  D0-D7
  13.  
  14.     6821 PIA                                  4000-4003   R/W  D0-D7
  15.  
  16.     HC55516 clock low, digit latch            6000        W    D0
  17.     HC55516 clock high                        6800        W    xx
  18.  
  19.     Bank select                               7800        W    D0-D2
  20.  
  21.     Banked Program ROM                        8000-FFFF   R    D0-D7
  22.  
  23. ****************************************************************************/
  24.  
  25. #include "driver.h"
  26. #include "machine/6821pia.h"
  27. #include "cpu/m6809/m6809.h"
  28. #include "williams.h"
  29.  
  30. #include <math.h>
  31.  
  32.  
  33. /***************************************************************************
  34.     COMPILER SWITCHES
  35. ****************************************************************************/
  36.  
  37. #define DISABLE_FIRQ_SPEEDUP        0
  38. #define DISABLE_LOOP_CATCHERS        0
  39.  
  40.  
  41. /***************************************************************************
  42.     CONSTANTS (from HC55516.c)
  43. ****************************************************************************/
  44.  
  45. #define    INTEGRATOR_LEAK_TC        0.001
  46. #define    FILTER_DECAY_TC            0.004
  47. #define    FILTER_CHARGE_TC        0.004
  48. #define    FILTER_MIN                0.0416
  49. #define    FILTER_MAX                1.0954
  50. #define    SAMPLE_GAIN                10000.0
  51.  
  52. #define WILLIAMS_CVSD            0
  53. #define WILLIAMS_ADPCM            1
  54. #define WILLIAMS_NARC            2
  55.  
  56.  
  57. /***************************************************************************
  58.     STRUCTURES
  59. ****************************************************************************/
  60.  
  61. struct ym2151_state
  62. {
  63.     double    timer_base;
  64.     double    timer_period[3];
  65.     UINT16    timer_value[2];
  66.     UINT8    timer_is_active[2];
  67.     UINT8    current_register;
  68.     UINT8    active_timer;
  69. };
  70.  
  71. struct counter_state
  72. {
  73.     UINT8 *    downcount;
  74.     UINT8 *    divisor;
  75.     UINT8 *    value;
  76.     UINT16    adjusted_divisor;
  77.     UINT16    last_hotspot_counter;
  78.     UINT16    hotspot_hit_count;
  79.     UINT16    hotspot_start;
  80.     UINT16    hotspot_stop;
  81.     UINT16    last_read_pc;
  82.     double    time_leftover;
  83.     void *    update_timer;
  84.     void *    enable_timer;
  85.     UINT8    invalid;
  86. };
  87.  
  88. struct cvsd_state
  89. {
  90.     UINT8 *    state;
  91.     UINT8 *    address;
  92.     UINT8 *    end;
  93.     UINT8 *    bank;
  94.     UINT32    bits_per_firq;
  95.     UINT32    sample_step;
  96.     UINT32    sample_position;
  97.     UINT16    current_sample;
  98.     UINT8    invalid;
  99.     double    charge;
  100.     double    decay;
  101.     double    leak;
  102.     double    integrator;
  103.     double    filter;
  104.     UINT8    shiftreg;
  105. };
  106.  
  107. struct dac_state
  108. {
  109.     UINT8 *    state_bank;
  110.     UINT8 *    address;
  111.     UINT8 *    end;
  112.     UINT8 *    volume;
  113.     UINT32    bytes_per_firq;
  114.     UINT32    sample_step;
  115.     UINT32    sample_position;
  116.     UINT16    current_sample;
  117.     UINT8    invalid;
  118. };
  119.  
  120.  
  121. /***************************************************************************
  122.     STATIC GLOBALS
  123. ****************************************************************************/
  124.  
  125. static UINT8 williams_cpunum;
  126. static UINT8 williams_pianum;
  127.  
  128. static UINT8 williams_audio_type;
  129.  
  130. static struct counter_state counter;
  131. static struct ym2151_state ym2151;
  132. static struct cvsd_state cvsd;
  133. static struct dac_state dac;
  134.  
  135. static int dac_stream;
  136. static int cvsd_stream;
  137.  
  138.  
  139.  
  140. /***************************************************************************
  141.     PROTOTYPES
  142. ****************************************************************************/
  143.  
  144. static void init_audio_state(int first_time);
  145. static void locate_audio_hotspot(UINT8 *base, UINT16 start);
  146.  
  147. static int williams_custom_start(const struct MachineSound *msound);
  148. static void williams_custom_stop(void);
  149. static void williams_custom_update(void);
  150.  
  151. static void williams_cvsd_ym2151_irq(int state);
  152. static void williams_adpcm_ym2151_irq(int state);
  153. static void williams_cvsd_irqa(int state);
  154. static void williams_cvsd_irqb(int state);
  155.  
  156. static READ_HANDLER( williams_cvsd_pia_r );
  157. static READ_HANDLER( williams_ym2151_r );
  158. static READ_HANDLER( counter_down_r );
  159. static READ_HANDLER( counter_value_r );
  160.  
  161. static WRITE_HANDLER( williams_dac_data_w );
  162. static WRITE_HANDLER( williams_dac2_data_w );
  163. static WRITE_HANDLER( williams_cvsd_pia_w );
  164. static WRITE_HANDLER( williams_ym2151_w );
  165. static WRITE_HANDLER( williams_cvsd_bank_select_w );
  166.  
  167. static READ_HANDLER( williams_adpcm_command_r );
  168. static WRITE_HANDLER( williams_adpcm_bank_select_w );
  169. static WRITE_HANDLER( williams_adpcm_6295_bank_select_w );
  170.  
  171. static READ_HANDLER( williams_narc_command_r );
  172. static READ_HANDLER( williams_narc_command2_r );
  173. static WRITE_HANDLER( williams_narc_command2_w );
  174. static WRITE_HANDLER( williams_narc_master_bank_select_w );
  175. static WRITE_HANDLER( williams_narc_slave_bank_select_w );
  176.  
  177. static void counter_enable(int param);
  178. static WRITE_HANDLER( counter_divisor_w );
  179. static WRITE_HANDLER( counter_down_w );
  180. static WRITE_HANDLER( counter_value_w );
  181.  
  182. static WRITE_HANDLER( cvsd_state_w );
  183. static WRITE_HANDLER( dac_state_bank_w );
  184.  
  185. static void update_counter(void);
  186. static void cvsd_update(int num, INT16 *buffer, int length);
  187. static void dac_update(int num, INT16 *buffer, int length);
  188.  
  189. static INT16 get_next_cvsd_sample(int bit);
  190.  
  191.  
  192. /***************************************************************************
  193.     PROCESSOR STRUCTURES
  194. ****************************************************************************/
  195.  
  196. /* CVSD readmem/writemem structures */
  197. struct MemoryReadAddress williams_cvsd_readmem[] =
  198. {
  199.     { 0x0000, 0x07ff, MRA_RAM },
  200.     { 0x2000, 0x2001, williams_ym2151_r },
  201.     { 0x4000, 0x4003, williams_cvsd_pia_r },
  202.     { 0x8000, 0xffff, MRA_BANK6 },
  203.     { -1 }
  204. };
  205.  
  206. struct MemoryWriteAddress williams_cvsd_writemem[] =
  207. {
  208.     { 0x0000, 0x07ff, MWA_RAM },
  209.     { 0x2000, 0x2001, williams_ym2151_w },
  210.     { 0x4000, 0x4003, williams_cvsd_pia_w },
  211.     { 0x6000, 0x6000, hc55516_0_digit_clock_clear_w },
  212.     { 0x6800, 0x6800, hc55516_0_clock_set_w },
  213.     { 0x7800, 0x7800, williams_cvsd_bank_select_w },
  214.     { 0x8000, 0xffff, MWA_ROM },
  215.     { -1 }
  216. };
  217.  
  218.  
  219. /* ADPCM readmem/writemem structures */
  220. struct MemoryReadAddress williams_adpcm_readmem[] =
  221. {
  222.     { 0x0000, 0x1fff, MRA_RAM },
  223.     { 0x2401, 0x2401, williams_ym2151_r },
  224.     { 0x2c00, 0x2c00, OKIM6295_status_0_r },
  225.     { 0x3000, 0x3000, williams_adpcm_command_r },
  226.     { 0x4000, 0xbfff, MRA_BANK6 },
  227.     { 0xc000, 0xffff, MRA_ROM },
  228.     { -1 }
  229. };
  230.  
  231. struct MemoryWriteAddress williams_adpcm_writemem[] =
  232. {
  233.     { 0x0000, 0x1fff, MWA_RAM },
  234.     { 0x2000, 0x2000, williams_adpcm_bank_select_w },
  235.     { 0x2400, 0x2401, williams_ym2151_w },
  236.     { 0x2800, 0x2800, williams_dac_data_w },
  237.     { 0x2c00, 0x2c00, OKIM6295_data_0_w },
  238.     { 0x3400, 0x3400, williams_adpcm_6295_bank_select_w }, /* PCM-BS */
  239.     { 0x3c00, 0x3c00, MWA_NOP },/*mk_sound_talkback_w }, -- talkback port? */
  240.     { 0x4000, 0xffff, MWA_ROM },
  241.     { -1 }
  242. };
  243.  
  244.  
  245. /* NARC master readmem/writemem structures */
  246. struct MemoryReadAddress williams_narc_master_readmem[] =
  247. {
  248.     { 0x0000, 0x1fff, MRA_RAM },
  249.     { 0x2001, 0x2001, williams_ym2151_r },
  250.     { 0x3000, 0x3000, MRA_NOP },
  251.     { 0x3400, 0x3400, williams_narc_command_r },
  252.     { 0x4000, 0xbfff, MRA_BANK6 },
  253.     { 0xc000, 0xffff, MRA_ROM },
  254.     { -1 }
  255. };
  256.  
  257. struct MemoryWriteAddress williams_narc_master_writemem[] =
  258. {
  259.     { 0x0000, 0x1fff, MWA_RAM },
  260.     { 0x2000, 0x2001, williams_ym2151_w },
  261.     { 0x2800, 0x2800, MWA_NOP },/*mk_sound_talkback_w }, -- talkback port? */
  262.     { 0x2c00, 0x2c00, williams_narc_command2_w },
  263.     { 0x3000, 0x3000, williams_dac_data_w },
  264.     { 0x3800, 0x3800, williams_narc_master_bank_select_w },
  265.     { 0x4000, 0xffff, MWA_ROM },
  266.     { -1 }
  267. };
  268.  
  269.  
  270. /* NARC slave readmem/writemem structures */
  271. struct MemoryReadAddress williams_narc_slave_readmem[] =
  272. {
  273.     { 0x0000, 0x1fff, MRA_RAM },
  274.     { 0x3000, 0x3000, MRA_NOP },
  275.     { 0x3400, 0x3400, williams_narc_command2_r },
  276.     { 0x4000, 0xbfff, MRA_BANK5 },
  277.     { 0xc000, 0xffff, MRA_ROM },
  278.     { -1 }
  279. };
  280.  
  281. struct MemoryWriteAddress williams_narc_slave_writemem[] =
  282. {
  283.     { 0x0000, 0x1fff, MWA_RAM },
  284.     { 0x2000, 0x2000, hc55516_0_clock_set_w },
  285.     { 0x2400, 0x2400, hc55516_0_digit_clock_clear_w },
  286.     { 0x3000, 0x3000, williams_dac2_data_w },
  287.     { 0x3800, 0x3800, williams_narc_slave_bank_select_w },
  288.     { 0x3c00, 0x3c00, MWA_NOP },
  289.     { 0x4000, 0xffff, MWA_ROM },
  290.     { -1 }
  291. };
  292.  
  293.  
  294. /* PIA structure */
  295. static struct pia6821_interface williams_cvsd_pia_intf =
  296. {
  297.     /*inputs : A/B,CA/B1,CA/B2 */ 0, 0, 0, 0, 0, 0,
  298.     /*outputs: A/B,CA/B2       */ williams_dac_data_w, 0, 0, 0,
  299.     /*irqs   : A/B             */ williams_cvsd_irqa, williams_cvsd_irqb
  300. };
  301.  
  302.  
  303. /***************************************************************************
  304.     AUDIO STRUCTURES
  305. ****************************************************************************/
  306.  
  307. /* Custom structure (all variants) */
  308. struct CustomSound_interface williams_custom_interface =
  309. {
  310.     williams_custom_start,
  311.     williams_custom_stop,
  312.     williams_custom_update
  313. };
  314.  
  315. /* YM2151 structure (CVSD variant) */
  316. struct YM2151interface williams_cvsd_ym2151_interface =
  317. {
  318.     1,            /* 1 chip */
  319.     3579580,
  320.     { YM3012_VOL(10,MIXER_PAN_CENTER,10,MIXER_PAN_CENTER) },
  321.     { williams_cvsd_ym2151_irq }
  322. };
  323.  
  324. /* YM2151 structure (ADPCM variant) */
  325. struct YM2151interface williams_adpcm_ym2151_interface =
  326. {
  327.     1,            /* 1 chip */
  328.     3579580,
  329.     { YM3012_VOL(10,MIXER_PAN_CENTER,10,MIXER_PAN_CENTER) },
  330.     { williams_adpcm_ym2151_irq }
  331. };
  332.  
  333. /* DAC structure (CVSD variant) */
  334. struct DACinterface williams_cvsd_dac_interface =
  335. {
  336.     1,
  337.     { 50 }
  338. };
  339.  
  340. /* DAC structure (ADPCM variant) */
  341. struct DACinterface williams_adpcm_dac_interface =
  342. {
  343.     1,
  344.     { 50 }
  345. };
  346.  
  347. /* DAC structure (NARC variant) */
  348. struct DACinterface williams_narc_dac_interface =
  349. {
  350.     2,
  351.     { 50, 50 }
  352. };
  353.  
  354. /* CVSD structure */
  355. struct hc55516_interface williams_cvsd_interface =
  356. {
  357.     1,            /* 1 chip */
  358.     { 80 }
  359. };
  360.  
  361. /* OKIM6295 structure(s) */
  362. struct OKIM6295interface williams_adpcm_6295_interface_REGION_SOUND1 =
  363. {
  364.     1,              /* 1 chip */
  365.     { 8000 },       /* 8000 Hz frequency */
  366.     { REGION_SOUND1 },  /* memory */
  367.     { 50 }
  368. };
  369.  
  370.  
  371. /***************************************************************************
  372.     INLINES
  373. ****************************************************************************/
  374.  
  375. INLINE UINT16 get_cvsd_address(void)
  376. {
  377.     if (cvsd.address)
  378.         return cvsd.address[0] * 256 + cvsd.address[1];
  379.     else
  380.         return cpunum_get_reg(williams_cpunum, M6809_Y);
  381. }
  382.  
  383. INLINE void set_cvsd_address(UINT16 address)
  384. {
  385.     if (cvsd.address)
  386.     {
  387.         cvsd.address[0] = address >> 8;
  388.         cvsd.address[1] = address;
  389.     }
  390.     else
  391.         cpunum_set_reg(williams_cpunum, M6809_Y, address);
  392. }
  393.  
  394. INLINE UINT16 get_dac_address(void)
  395. {
  396.     if (dac.address)
  397.         return dac.address[0] * 256 + dac.address[1];
  398.     else
  399.         return cpunum_get_reg(williams_cpunum, M6809_Y);
  400. }
  401.  
  402. INLINE void set_dac_address(UINT16 address)
  403. {
  404.     if (dac.address)
  405.     {
  406.         dac.address[0] = address >> 8;
  407.         dac.address[1] = address;
  408.     }
  409.     else
  410.         cpunum_set_reg(williams_cpunum, M6809_Y, address);
  411. }
  412.  
  413. INLINE UINT8 *get_cvsd_bank_base(int data)
  414. {
  415.     UINT8 *RAM = memory_region(REGION_CPU1+williams_cpunum);
  416.     int bank = data & 3;
  417.     int quarter = (data >> 2) & 3;
  418.     if (bank == 3) bank = 0;
  419.     return &RAM[0x10000 + (bank * 0x20000) + (quarter * 0x8000)];
  420. }
  421.  
  422. INLINE UINT8 *get_adpcm_bank_base(int data)
  423. {
  424.     UINT8 *RAM = memory_region(REGION_CPU1+williams_cpunum);
  425.     int bank = data & 7;
  426.     return &RAM[0x10000 + (bank * 0x8000)];
  427. }
  428.  
  429. INLINE UINT8 *get_narc_master_bank_base(int data)
  430. {
  431.     UINT8 *RAM = memory_region(REGION_CPU1+williams_cpunum);
  432.     int bank = data & 3;
  433.     if (!(data & 4)) bank = 0;
  434.     return &RAM[0x10000 + (bank * 0x8000)];
  435. }
  436.  
  437. INLINE UINT8 *get_narc_slave_bank_base(int data)
  438. {
  439.     UINT8 *RAM = memory_region(REGION_CPU1+williams_cpunum + 1);
  440.     int bank = data & 7;
  441.     return &RAM[0x10000 + (bank * 0x8000)];
  442. }
  443.  
  444.  
  445. /***************************************************************************
  446.     INITIALIZATION
  447. ****************************************************************************/
  448.  
  449. void williams_cvsd_init(int cpunum, int pianum)
  450. {
  451.     UINT16 entry_point;
  452.     UINT8 *RAM;
  453.  
  454.     /* configure the CPU */
  455.     williams_cpunum = cpunum;
  456.     williams_audio_type = WILLIAMS_CVSD;
  457.  
  458.     /* configure the PIA */
  459.     williams_pianum = pianum;
  460.     pia_config(pianum, PIA_STANDARD_ORDERING | PIA_8BIT, &williams_cvsd_pia_intf);
  461.  
  462.     /* reset the chip */
  463.     williams_cvsd_reset_w(1);
  464.     williams_cvsd_reset_w(0);
  465.  
  466.     /* determine the entry point; from there, we can choose the speedup addresses */
  467.     RAM = memory_region(REGION_CPU1+cpunum);
  468.     entry_point = RAM[0x17ffe] * 256 + RAM[0x17fff];
  469.     switch (entry_point)
  470.     {
  471.         /* Joust 2 case */
  472.         case 0x8045:
  473.             counter.downcount     = install_mem_write_handler(cpunum, 0x217, 0x217, counter_down_w);
  474.             counter.divisor = install_mem_write_handler(cpunum, 0x216, 0x216, counter_divisor_w);
  475.             counter.value     = install_mem_write_handler(cpunum, 0x214, 0x215, counter_value_w);
  476.  
  477.             install_mem_read_handler(cpunum, 0x217, 0x217, counter_down_r);
  478.             install_mem_read_handler(cpunum, 0x214, 0x215, counter_value_r);
  479.  
  480.             cvsd.state        = install_mem_write_handler(cpunum, 0x220, 0x221, cvsd_state_w);
  481.             cvsd.address    = NULL;    /* in Y */
  482.             cvsd.end        = &RAM[0x21d];
  483.             cvsd.bank        = &RAM[0x21f];
  484.             cvsd.bits_per_firq = 1;
  485.  
  486.             dac.state_bank    = NULL;
  487.             dac.address        = NULL;
  488.             dac.end            = NULL;
  489.             dac.volume        = NULL;
  490.             dac.bytes_per_firq = 0;
  491.             break;
  492.  
  493.         /* Arch Rivals case */
  494.         case 0x8067:
  495.             counter.downcount     = install_mem_write_handler(cpunum, 0x239, 0x239, counter_down_w);
  496.             counter.divisor = install_mem_write_handler(cpunum, 0x238, 0x238, counter_divisor_w);
  497.             counter.value     = install_mem_write_handler(cpunum, 0x236, 0x237, counter_value_w);
  498.  
  499.             install_mem_read_handler(cpunum, 0x239, 0x239, counter_down_r);
  500.             install_mem_read_handler(cpunum, 0x236, 0x237, counter_value_r);
  501.  
  502.             cvsd.state        = install_mem_write_handler(cpunum, 0x23e, 0x23f, cvsd_state_w);
  503.             cvsd.address    = NULL;    /* in Y */
  504.             cvsd.end        = &RAM[0x242];
  505.             cvsd.bank        = &RAM[0x22b];
  506.             cvsd.bits_per_firq = 1;
  507.  
  508.             dac.state_bank    = NULL;
  509.             dac.address        = NULL;
  510.             dac.end            = NULL;
  511.             dac.volume        = NULL;
  512.             dac.bytes_per_firq = 0;
  513.             break;
  514.  
  515.         /* General CVSD case */
  516.         case 0x80c8:
  517.             counter.downcount     = install_mem_write_handler(cpunum, 0x23a, 0x23a, counter_down_w);
  518.             counter.divisor = install_mem_write_handler(cpunum, 0x238, 0x238, counter_divisor_w);
  519.             counter.value     = install_mem_write_handler(cpunum, 0x236, 0x237, counter_value_w);
  520.  
  521.             install_mem_read_handler(cpunum, 0x23a, 0x23a, counter_down_r);
  522.             install_mem_read_handler(cpunum, 0x236, 0x237, counter_value_r);
  523.  
  524.             cvsd.state        = install_mem_write_handler(cpunum, 0x23f, 0x240, cvsd_state_w);
  525.             cvsd.address    = &RAM[0x241];
  526.             cvsd.end        = &RAM[0x243];
  527.             cvsd.bank        = &RAM[0x22b];
  528.             cvsd.bits_per_firq = 4;
  529.  
  530.             dac.state_bank    = install_mem_write_handler(cpunum, 0x22c, 0x22c, dac_state_bank_w);
  531.             dac.address        = NULL;    /* in Y */
  532.             dac.end            = &RAM[0x234];
  533.             dac.volume        = &RAM[0x231];
  534.             dac.bytes_per_firq = 2;
  535.             break;
  536.     }
  537.  
  538.     /* find the hotspot for optimization */
  539.     locate_audio_hotspot(&RAM[0x8000], 0x8000);
  540.  
  541.     /* reset the IRQ state */
  542.     pia_set_input_ca1(williams_pianum, 1);
  543.  
  544.     /* initialize the global variables */
  545.     init_audio_state(1);
  546. }
  547.  
  548. void williams_adpcm_init(int cpunum)
  549. {
  550.     UINT16 entry_point;
  551.     UINT8 *RAM;
  552.  
  553.     /* configure the CPU */
  554.     williams_cpunum = cpunum;
  555.     williams_audio_type = WILLIAMS_ADPCM;
  556.  
  557.     /* install the fixed ROM */
  558.     RAM = memory_region(REGION_CPU1+cpunum);
  559.     memcpy(&RAM[0xc000], &RAM[0x4c000], 0x4000);
  560.  
  561.     /* reset the chip */
  562.     williams_adpcm_reset_w(1);
  563.     williams_adpcm_reset_w(0);
  564.  
  565.     /* determine the entry point; from there, we can choose the speedup addresses */
  566.     entry_point = RAM[0xfffe] * 256 + RAM[0xffff];
  567.     switch (entry_point)
  568.     {
  569.         /* General ADPCM case */
  570.         case 0xdd51:
  571.         case 0xdd55:
  572.             counter.downcount     = install_mem_write_handler(cpunum, 0x238, 0x238, counter_down_w);
  573.             counter.divisor = install_mem_write_handler(cpunum, 0x236, 0x236, counter_divisor_w);
  574.             counter.value     = install_mem_write_handler(cpunum, 0x234, 0x235, counter_value_w);
  575.  
  576.             install_mem_read_handler(cpunum, 0x238, 0x238, counter_down_r);
  577.             install_mem_read_handler(cpunum, 0x234, 0x235, counter_value_r);
  578.  
  579.             cvsd.state        = NULL;
  580.             cvsd.address    = NULL;
  581.             cvsd.end        = NULL;
  582.             cvsd.bank        = NULL;
  583.             cvsd.bits_per_firq = 0;
  584.  
  585.             dac.state_bank    = install_mem_write_handler(cpunum, 0x23a, 0x23a, dac_state_bank_w);
  586.             dac.address        = NULL;    /* in Y */
  587.             dac.end            = &RAM[0x232];
  588.             dac.volume        = &RAM[0x22f];
  589.             dac.bytes_per_firq = 1;
  590.             break;
  591.  
  592.         /* Unknown case */
  593.         default:
  594.             break;
  595.     }
  596.  
  597.     /* find the hotspot for optimization */
  598. //    locate_audio_hotspot(&RAM[0x40000], 0xc000);
  599.  
  600.     /* initialize the global variables */
  601.     init_audio_state(1);
  602. }
  603.  
  604. void williams_narc_init(int cpunum)
  605. {
  606.     UINT16 entry_point;
  607.     UINT8 *RAM;
  608.  
  609.     /* configure the CPU */
  610.     williams_cpunum = cpunum;
  611.     williams_audio_type = WILLIAMS_NARC;
  612.  
  613.     /* install the fixed ROM */
  614.     RAM = memory_region(REGION_CPU1+cpunum + 1);
  615.     memcpy(&RAM[0xc000], &RAM[0x4c000], 0x4000);
  616.     RAM = memory_region(REGION_CPU1+cpunum);
  617.     memcpy(&RAM[0xc000], &RAM[0x2c000], 0x4000);
  618.  
  619.     /* reset the chip */
  620.     williams_narc_reset_w(1);
  621.     williams_narc_reset_w(0);
  622.  
  623.     /* determine the entry point; from there, we can choose the speedup addresses */
  624.     entry_point = RAM[0xfffe] * 256 + RAM[0xffff];
  625.     switch (entry_point)
  626.     {
  627.         /* General ADPCM case */
  628.         case 0xc060:
  629.             counter.downcount     = install_mem_write_handler(cpunum, 0x249, 0x249, counter_down_w);
  630.             counter.divisor = install_mem_write_handler(cpunum, 0x248, 0x248, counter_divisor_w);
  631.             counter.value     = install_mem_write_handler(cpunum, 0x246, 0x247, counter_value_w);
  632.  
  633.             install_mem_read_handler(cpunum, 0x249, 0x249, counter_down_r);
  634.             install_mem_read_handler(cpunum, 0x246, 0x247, counter_value_r);
  635.  
  636.             cvsd.state        = NULL;
  637.             cvsd.address    = NULL;
  638.             cvsd.end        = NULL;
  639.             cvsd.bank        = NULL;
  640.             cvsd.bits_per_firq = 0;
  641.  
  642.             dac.state_bank    = install_mem_write_handler(cpunum, 0x23c, 0x23c, dac_state_bank_w);
  643.             dac.address        = NULL;    /* in Y */
  644.             dac.end            = &RAM[0x244];
  645.             dac.volume        = &RAM[0x241];
  646.             dac.bytes_per_firq = 1;
  647.             break;
  648.  
  649.         /* Unknown case */
  650.         default:
  651.             break;
  652.     }
  653.  
  654.     /* find the hotspot for optimization */
  655.     locate_audio_hotspot(&RAM[0x0000], 0xc000);
  656.  
  657.     /* initialize the global variables */
  658.     init_audio_state(1);
  659. }
  660.  
  661. static void init_audio_state(int first_time)
  662. {
  663.     /* reset the YM2151 state */
  664.     ym2151.timer_base = 1.0 / (3579580.0 / 64.0);
  665.     ym2151.timer_period[0] = ym2151.timer_period[1] = ym2151.timer_period[2] = 1.0;
  666.     ym2151.timer_value[0] = ym2151.timer_value[1] = 0;
  667.     ym2151.timer_is_active[0] = ym2151.timer_is_active[1] = 0;
  668.     ym2151.current_register = 0x13;
  669.     ym2151.active_timer = 2;
  670.     YM2151_sh_reset();
  671.  
  672.     /* reset the counter state */
  673.     counter.adjusted_divisor = 256;
  674.     counter.last_hotspot_counter = 0xffff;
  675.     counter.hotspot_hit_count = 0;
  676.     counter.time_leftover = 0;
  677.     counter.last_read_pc = 0x0000;
  678.     if (first_time)
  679.         counter.update_timer = timer_set(TIME_NEVER, 0, NULL);
  680.     counter.invalid = 1;
  681.     if (!first_time && counter.enable_timer)
  682.         timer_remove(counter.enable_timer);
  683.     counter.enable_timer = timer_set(TIME_IN_SEC(3), 0, counter_enable);
  684.  
  685.     /* reset the CVSD generator */
  686.     cvsd.sample_step = 0;
  687.     cvsd.sample_position = 0x10000;
  688.     cvsd.current_sample = 0;
  689.     cvsd.invalid = 1;
  690.     cvsd.charge = pow(exp(-1), 1.0 / (FILTER_CHARGE_TC * 16000.0));
  691.     cvsd.decay = pow(exp(-1), 1.0 / (FILTER_DECAY_TC * 16000.0));
  692.     cvsd.leak = pow(exp(-1), 1.0 / (INTEGRATOR_LEAK_TC * 16000.0));
  693.     cvsd.integrator = 0;
  694.     cvsd.filter = FILTER_MIN;
  695.     cvsd.shiftreg = 0xaa;
  696.  
  697.     /* reset the DAC generator */
  698.     dac.sample_step = 0;
  699.     dac.sample_position = 0x10000;
  700.     dac.current_sample = 0;
  701.     dac.invalid = 1;
  702.  
  703.     /* clear all the interrupts */
  704.     cpu_set_irq_line(williams_cpunum, M6809_FIRQ_LINE, CLEAR_LINE);
  705.     cpu_set_irq_line(williams_cpunum, M6809_IRQ_LINE, CLEAR_LINE);
  706.     cpu_set_nmi_line(williams_cpunum, CLEAR_LINE);
  707.     if (williams_audio_type == WILLIAMS_NARC)
  708.     {
  709.         cpu_set_irq_line(williams_cpunum + 1, M6809_FIRQ_LINE, CLEAR_LINE);
  710.         cpu_set_irq_line(williams_cpunum + 1, M6809_IRQ_LINE, CLEAR_LINE);
  711.         cpu_set_nmi_line(williams_cpunum + 1, CLEAR_LINE);
  712.     }
  713. }
  714.  
  715. static void locate_audio_hotspot(UINT8 *base, UINT16 start)
  716. {
  717.     int i;
  718.  
  719.     /* search for the loop that kills performance so we can optimize it */
  720.     for (i = start; i < 0x10000; i++)
  721.     {
  722.         if (base[i + 0] == 0x1a && base[i + 1] == 0x50 &&            /* 1A 50       ORCC  #$0050  */
  723.             base[i + 2] == 0x93 &&                                    /* 93 xx       SUBD  $xx     */
  724.             base[i + 4] == 0xe3 && base[i + 5] == 0x4c &&            /* E3 4C       ADDD  $000C,U */
  725.             base[i + 6] == 0x9e && base[i + 7] == base[i + 3] &&    /* 9E xx       LDX   $xx     */
  726.             base[i + 8] == 0xaf && base[i + 9] == 0x4c &&            /* AF 4C       STX   $000C,U */
  727.             base[i +10] == 0x1c && base[i +11] == 0xaf)                /* 1C AF       ANDCC #$00AF  */
  728.         {
  729.             counter.hotspot_start = i;
  730.             counter.hotspot_stop = i + 12;
  731.             logerror("Found hotspot @ %04X", i);
  732.             return;
  733.         }
  734.     }
  735.     logerror("Found no hotspot!");
  736. }
  737.  
  738.  
  739. /***************************************************************************
  740.     CUSTOM SOUND INTERFACES
  741. ****************************************************************************/
  742.  
  743. static int williams_custom_start(const struct MachineSound *msound)
  744. {
  745.     (void)msound;
  746.  
  747.     /* allocate a DAC stream */
  748.     dac_stream = stream_init("Accelerated DAC", 50, Machine->sample_rate, 0, dac_update);
  749.  
  750.     /* allocate a CVSD stream */
  751.     cvsd_stream = stream_init("Accelerated CVSD", 50, Machine->sample_rate, 0, cvsd_update);
  752.  
  753.     return 0;
  754. }
  755.  
  756. static void williams_custom_stop(void)
  757. {
  758. }
  759.  
  760. static void williams_custom_update(void)
  761. {
  762. }
  763.  
  764.  
  765. /***************************************************************************
  766.     CVSD IRQ GENERATION CALLBACKS
  767. ****************************************************************************/
  768.  
  769. static void williams_cvsd_ym2151_irq(int state)
  770. {
  771.     pia_set_input_ca1(williams_pianum, !state);
  772. }
  773.  
  774. static void williams_cvsd_irqa(int state)
  775. {
  776.     cpu_set_irq_line(williams_cpunum, M6809_FIRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE);
  777. }
  778.  
  779. static void williams_cvsd_irqb(int state)
  780. {
  781.     cpu_set_nmi_line(williams_cpunum, state ? ASSERT_LINE : CLEAR_LINE);
  782. }
  783.  
  784.  
  785. /***************************************************************************
  786.     ADPCM IRQ GENERATION CALLBACKS
  787. ****************************************************************************/
  788.  
  789. static void williams_adpcm_ym2151_irq(int state)
  790. {
  791.     cpu_set_irq_line(williams_cpunum, M6809_FIRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE);
  792. }
  793.  
  794.  
  795. /***************************************************************************
  796.     CVSD BANK SELECT
  797. ****************************************************************************/
  798.  
  799. WRITE_HANDLER( williams_cvsd_bank_select_w )
  800. {
  801.     cpu_setbank(6, get_cvsd_bank_base(data));
  802. }
  803.  
  804.  
  805. /***************************************************************************
  806.     ADPCM BANK SELECT
  807. ****************************************************************************/
  808.  
  809. WRITE_HANDLER( williams_adpcm_bank_select_w )
  810. {
  811.     cpu_setbank(6, get_adpcm_bank_base(data));
  812. }
  813.  
  814. WRITE_HANDLER( williams_adpcm_6295_bank_select_w )
  815. {
  816.     if (!(data & 0x04))
  817.         OKIM6295_set_bank_base(0, ALL_VOICES, 0x00000);
  818.     else if (data & 0x01)
  819.         OKIM6295_set_bank_base(0, ALL_VOICES, 0x40000);
  820.     else
  821.         OKIM6295_set_bank_base(0, ALL_VOICES, 0x80000);
  822. }
  823.  
  824.  
  825. /***************************************************************************
  826.     NARC BANK SELECT
  827. ****************************************************************************/
  828.  
  829. WRITE_HANDLER( williams_narc_master_bank_select_w )
  830. {
  831.     cpu_setbank(6, get_narc_master_bank_base(data));
  832. }
  833.  
  834. WRITE_HANDLER( williams_narc_slave_bank_select_w )
  835. {
  836.     cpu_setbank(5, get_narc_slave_bank_base(data));
  837. }
  838.  
  839.  
  840. /***************************************************************************
  841.     CVSD COMMUNICATIONS
  842. ****************************************************************************/
  843.  
  844. static void williams_cvsd_delayed_data_w(int param)
  845. {
  846.     pia_set_input_b(williams_pianum, param & 0xff);
  847.     pia_set_input_cb1(williams_pianum, param & 0x100);
  848.     pia_set_input_cb2(williams_pianum, param & 0x200);
  849. }
  850.  
  851. WRITE_HANDLER( williams_cvsd_data_w )
  852. {
  853.     timer_set(TIME_NOW, data, williams_cvsd_delayed_data_w);
  854. }
  855.  
  856. void williams_cvsd_reset_w(int state)
  857. {
  858.     /* going high halts the CPU */
  859.     if (state)
  860.     {
  861.         williams_cvsd_bank_select_w(0, 0);
  862.         init_audio_state(0);
  863.         cpu_set_reset_line(williams_cpunum, ASSERT_LINE);
  864.     }
  865.     /* going low resets and reactivates the CPU */
  866.     else
  867.         cpu_set_reset_line(williams_cpunum, CLEAR_LINE);
  868. }
  869.  
  870.  
  871. /***************************************************************************
  872.     ADPCM COMMUNICATIONS
  873. ****************************************************************************/
  874.  
  875. READ_HANDLER( williams_adpcm_command_r )
  876. {
  877.     cpu_set_irq_line(williams_cpunum, M6809_IRQ_LINE, CLEAR_LINE);
  878.     return soundlatch_r(0);
  879. }
  880.  
  881. WRITE_HANDLER( williams_adpcm_data_w )
  882. {
  883.     soundlatch_w(0, data & 0xff);
  884.     if (!(data & 0x200))
  885.         cpu_set_irq_line(williams_cpunum, M6809_IRQ_LINE, ASSERT_LINE);
  886. }
  887.  
  888. void williams_adpcm_reset_w(int state)
  889. {
  890.     /* going high halts the CPU */
  891.     if (state)
  892.     {
  893.         williams_adpcm_bank_select_w(0, 0);
  894.         init_audio_state(0);
  895.         cpu_set_reset_line(williams_cpunum, ASSERT_LINE);
  896.     }
  897.     /* going low resets and reactivates the CPU */
  898.     else
  899.         cpu_set_reset_line(williams_cpunum, CLEAR_LINE);
  900. }
  901.  
  902.  
  903. /***************************************************************************
  904.     NARC COMMUNICATIONS
  905. ****************************************************************************/
  906.  
  907. READ_HANDLER( williams_narc_command_r )
  908. {
  909.     cpu_set_nmi_line(williams_cpunum, CLEAR_LINE);
  910.     cpu_set_irq_line(williams_cpunum, M6809_IRQ_LINE, CLEAR_LINE);
  911.     return soundlatch_r(0);
  912. }
  913.  
  914. WRITE_HANDLER( williams_narc_data_w )
  915. {
  916.     soundlatch_w(0, data & 0xff);
  917.     if (!(data & 0x100))
  918.         cpu_set_nmi_line(williams_cpunum, ASSERT_LINE);
  919.     if (!(data & 0x200))
  920.         cpu_set_irq_line(williams_cpunum, M6809_IRQ_LINE, ASSERT_LINE);
  921. }
  922.  
  923. void williams_narc_reset_w(int state)
  924. {
  925.     /* going high halts the CPU */
  926.     if (state)
  927.     {
  928.         williams_narc_master_bank_select_w(0, 0);
  929.         williams_narc_slave_bank_select_w(0, 0);
  930.         init_audio_state(0);
  931.         cpu_set_reset_line(williams_cpunum, ASSERT_LINE);
  932.         cpu_set_reset_line(williams_cpunum + 1, ASSERT_LINE);
  933.     }
  934.     /* going low resets and reactivates the CPU */
  935.     else
  936.     {
  937.         cpu_set_reset_line(williams_cpunum, CLEAR_LINE);
  938.         cpu_set_reset_line(williams_cpunum + 1, CLEAR_LINE);
  939.     }
  940. }
  941.  
  942. READ_HANDLER( williams_narc_command2_r )
  943. {
  944.     cpu_set_irq_line(williams_cpunum + 1, M6809_FIRQ_LINE, CLEAR_LINE);
  945.     return soundlatch2_r(0);
  946. }
  947.  
  948. WRITE_HANDLER( williams_narc_command2_w )
  949. {
  950.     soundlatch2_w(0, data & 0xff);
  951.     cpu_set_irq_line(williams_cpunum + 1, M6809_FIRQ_LINE, ASSERT_LINE);
  952. }
  953.  
  954.  
  955. /***************************************************************************
  956.     YM2151 INTERFACES
  957. ****************************************************************************/
  958.  
  959. static READ_HANDLER( williams_ym2151_r )
  960. {
  961.     return YM2151_status_port_0_r(offset);
  962. }
  963.  
  964. static WRITE_HANDLER( williams_ym2151_w )
  965. {
  966.     if (offset & 1)
  967.     {
  968.         /* handle timer registers here */
  969.         switch (ym2151.current_register)
  970.         {
  971.             case 0x10:    /* timer A, upper 8 bits */
  972.                 update_counter();
  973.                 ym2151.timer_value[0] = (ym2151.timer_value[0] & 0x003) | (data << 2);
  974.                 ym2151.timer_period[0] = ym2151.timer_base * (double)(1024 - ym2151.timer_value[0]);
  975.                 break;
  976.  
  977.             case 0x11:    /* timer A, upper 8 bits */
  978.                 update_counter();
  979.                 ym2151.timer_value[0] = (ym2151.timer_value[0] & 0x3fc) | (data & 0x03);
  980.                 ym2151.timer_period[0] = ym2151.timer_base * (double)(1024 - ym2151.timer_value[0]);
  981.                 break;
  982.  
  983.             case 0x12:    /* timer B */
  984.                 update_counter();
  985.                 ym2151.timer_value[1] = data;
  986.                 ym2151.timer_period[1] = ym2151.timer_base * (double)((256 - ym2151.timer_value[1]) << 4);
  987.                 break;
  988.  
  989.             case 0x14:    /* timer control */
  990.  
  991.                 /* enable/disable timer A */
  992.                 if ((data & 0x01) && (data & 0x04) && !ym2151.timer_is_active[0])
  993.                 {
  994.                     update_counter();
  995.                     ym2151.timer_is_active[0] = 1;
  996.                     ym2151.active_timer = 0;
  997.                 }
  998.                 else if (!(data & 0x01) && ym2151.timer_is_active[0])
  999.                 {
  1000.                     ym2151.timer_is_active[0] = 0;
  1001.                     ym2151.active_timer = ym2151.timer_is_active[1] ? 1 : 2;
  1002.                 }
  1003.  
  1004.                 /* enable/disable timer B */
  1005.                 if ((data & 0x02) && (data & 0x08) && !ym2151.timer_is_active[1])
  1006.                 {
  1007.                     update_counter();
  1008.                     ym2151.timer_is_active[1] = 1;
  1009.                     ym2151.active_timer = 1;
  1010.                 }
  1011.                 else if (!(data & 0x02) && ym2151.timer_is_active[1])
  1012.                 {
  1013.                     ym2151.timer_is_active[1] = 0;
  1014.                     ym2151.active_timer = ym2151.timer_is_active[0] ? 0 : 2;
  1015.                 }
  1016.                 break;
  1017.  
  1018.             default:    /* pass through everything else */
  1019.                 YM2151_data_port_0_w(offset, data);
  1020.                 break;
  1021.         }
  1022.     }
  1023.     else
  1024.     {
  1025.         if (!DISABLE_FIRQ_SPEEDUP)
  1026.             ym2151.current_register = data;
  1027.  
  1028.         /* only pass through register writes for non-timer registers */
  1029.         if (DISABLE_FIRQ_SPEEDUP || ym2151.current_register < 0x10 || ym2151.current_register > 0x14)
  1030.             YM2151_register_port_0_w(offset, data);
  1031.     }
  1032. }
  1033.  
  1034.  
  1035. /***************************************************************************
  1036.     PIA INTERFACES
  1037. ****************************************************************************/
  1038.  
  1039. static READ_HANDLER( williams_cvsd_pia_r )
  1040. {
  1041.     return pia_read(williams_pianum, offset);
  1042. }
  1043.  
  1044. static WRITE_HANDLER( williams_cvsd_pia_w )
  1045. {
  1046.     pia_write(williams_pianum, offset, data);
  1047. }
  1048.  
  1049.  
  1050. /***************************************************************************
  1051.     DAC INTERFACES
  1052. ****************************************************************************/
  1053.  
  1054. static WRITE_HANDLER( williams_dac_data_w )
  1055. {
  1056.     DAC_data_w(0, data);
  1057. }
  1058.  
  1059. static WRITE_HANDLER( williams_dac2_data_w )
  1060. {
  1061.     DAC_data_w(1, data);
  1062. }
  1063.  
  1064.  
  1065. /***************************************************************************
  1066.     SPEEDUP KLUDGES
  1067. ****************************************************************************/
  1068.  
  1069. static void counter_enable(int param)
  1070. {
  1071.     counter.invalid = 0;
  1072.     counter.enable_timer = NULL;
  1073.     timer_reset(counter.update_timer, TIME_NEVER);
  1074.  
  1075.     /* the counter routines all reset the bank, but NARC is the only one that cares */
  1076.     if (williams_audio_type == WILLIAMS_NARC)
  1077.         williams_narc_master_bank_select_w(0, 5);
  1078. }
  1079.  
  1080. static void update_counter(void)
  1081. {
  1082.     double time_since_update, timer_period = ym2151.timer_period[ym2151.active_timer];
  1083.     int firqs_since_update, complete_ticks, downcounter;
  1084.  
  1085.     if (DISABLE_FIRQ_SPEEDUP || ym2151.active_timer == 2 || counter.invalid)
  1086.         return;
  1087.  
  1088.     /* compute the time since we last updated; if it's less than one period, do nothing */
  1089.     time_since_update = timer_timeelapsed(counter.update_timer) + counter.time_leftover;
  1090.     if (time_since_update < timer_period)
  1091.         return;
  1092.  
  1093.     /* compute the integral number of FIRQ interrupts that have occured since the last update */
  1094.     firqs_since_update = (int)(time_since_update / timer_period);
  1095.  
  1096.     /* keep track of any additional time */
  1097.     counter.time_leftover = time_since_update - (double)firqs_since_update * timer_period;
  1098.  
  1099.     /* reset the timer */
  1100.     timer_reset(counter.update_timer, TIME_NEVER);
  1101.  
  1102.     /* determine the number of complete ticks that have occurred */
  1103.     complete_ticks = firqs_since_update / counter.adjusted_divisor;
  1104.  
  1105.     /* subtract any remainder from the down counter, and carry if appropriate */
  1106.     downcounter = counter.downcount[0] - (firqs_since_update - complete_ticks * counter.adjusted_divisor);
  1107.     if (downcounter < 0)
  1108.     {
  1109.         downcounter += counter.adjusted_divisor;
  1110.         complete_ticks++;
  1111.     }
  1112.  
  1113.     /* add in the previous value of the counter */
  1114.     complete_ticks += counter.value[0] * 256 + counter.value[1];
  1115.  
  1116.     /* store the results */
  1117.     counter.value[0] = complete_ticks >> 8;
  1118.     counter.value[1] = complete_ticks;
  1119.     counter.downcount[0] = downcounter;
  1120. }
  1121.  
  1122. static WRITE_HANDLER( counter_divisor_w )
  1123. {
  1124.     update_counter();
  1125.     counter.divisor[offset] = data;
  1126.     counter.adjusted_divisor = data ? data : 256;
  1127. }
  1128.  
  1129. static READ_HANDLER( counter_down_r )
  1130. {
  1131.     update_counter();
  1132.     return counter.downcount[offset];
  1133. }
  1134.  
  1135. static WRITE_HANDLER( counter_down_w )
  1136. {
  1137.     update_counter();
  1138.     counter.downcount[offset] = data;
  1139. }
  1140.  
  1141. static READ_HANDLER( counter_value_r )
  1142. {
  1143.     UINT16 pc = cpu_getpreviouspc();
  1144.  
  1145.     /* only update the counter on the MSB */
  1146.     /* also, don't update it if we just read from it a few instructions back */
  1147.     if (offset == 0 && (pc <= counter.last_read_pc || pc > counter.last_read_pc + 16))
  1148.         update_counter();
  1149.     counter.last_read_pc = pc;
  1150.  
  1151.     /* on the second LSB read in the hotspot, check to see if we will be looping */
  1152.     if (offset == 1 && pc == counter.hotspot_start + 6 && !DISABLE_LOOP_CATCHERS)
  1153.     {
  1154.         UINT16 new_counter = counter.value[0] * 256 + counter.value[1];
  1155.  
  1156.         /* count how many hits in a row we got the same value */
  1157.         if (new_counter == counter.last_hotspot_counter)
  1158.             counter.hotspot_hit_count++;
  1159.         else
  1160.             counter.hotspot_hit_count = 0;
  1161.         counter.last_hotspot_counter = new_counter;
  1162.  
  1163.         /* more than 3 hits in a row and we optimize */
  1164.         if (counter.hotspot_hit_count > 3)
  1165.             *cpuintf[Machine->drv->cpu[williams_cpunum].cpu_type & ~CPU_FLAGS_MASK].icount -= 50;
  1166.     }
  1167.  
  1168.     return counter.value[offset];
  1169. }
  1170.  
  1171. static WRITE_HANDLER( counter_value_w )
  1172. {
  1173.     /* only update the counter after the LSB is written */
  1174.     if (offset == 1)
  1175.         update_counter();
  1176.     counter.value[offset] = data;
  1177.     counter.hotspot_hit_count = 0;
  1178. }
  1179.  
  1180.  
  1181. /***************************************************************************
  1182.     CVSD KLUDGES
  1183. ****************************************************************************/
  1184.  
  1185. static void cvsd_start(int param)
  1186. {
  1187.     double sample_rate;
  1188.     int start, end;
  1189.  
  1190.     /* if interrupts are disabled, try again later */
  1191.     if (cpunum_get_reg(williams_cpunum, M6809_CC) & 0x40)
  1192.     {
  1193.         timer_set(TIME_IN_MSEC(1), 0, cvsd_start);
  1194.         return;
  1195.     }
  1196.  
  1197.     /* determine the start and end addresses */
  1198.     start = get_cvsd_address();
  1199.     end = cvsd.end[0] * 256 + cvsd.end[1];
  1200.  
  1201.     /* compute the effective sample rate */
  1202.     sample_rate = (double)cvsd.bits_per_firq / ym2151.timer_period[ym2151.active_timer];
  1203.     cvsd.sample_step = (int)(sample_rate * 65536.0 / (double)Machine->sample_rate);
  1204.     cvsd.invalid = 0;
  1205. }
  1206.  
  1207. static WRITE_HANDLER( cvsd_state_w )
  1208. {
  1209.     /* if we write a value here with a non-zero high bit, prepare to start playing */
  1210.     stream_update(cvsd_stream, 0);
  1211.     if (offset == 0 && !(data & 0x80) && ym2151.active_timer != 2)
  1212.     {
  1213.         cvsd.invalid = 1;
  1214.         timer_set(TIME_IN_MSEC(1), 0, cvsd_start);
  1215.     }
  1216.  
  1217.     cvsd.state[offset] = data;
  1218. }
  1219.  
  1220.  
  1221. /***************************************************************************
  1222.     DAC KLUDGES
  1223. ****************************************************************************/
  1224.  
  1225. static void dac_start(int param)
  1226. {
  1227.     double sample_rate;
  1228.     int start, end;
  1229.  
  1230.     /* if interrupts are disabled, try again later */
  1231.     if (cpunum_get_reg(williams_cpunum, M6809_CC) & 0x40)
  1232.     {
  1233.         timer_set(TIME_IN_MSEC(1), 0, dac_start);
  1234.         return;
  1235.     }
  1236.  
  1237.     /* determine the start and end addresses */
  1238.     start = get_dac_address();
  1239.     end = dac.end[0] * 256 + dac.end[1];
  1240.  
  1241.     /* compute the effective sample rate */
  1242.     sample_rate = (double)dac.bytes_per_firq / ym2151.timer_period[ym2151.active_timer];
  1243.     dac.sample_step = (int)(sample_rate * 65536.0 / (double)Machine->sample_rate);
  1244.     dac.invalid = 0;
  1245. }
  1246.  
  1247. static WRITE_HANDLER( dac_state_bank_w )
  1248. {
  1249.     /* if we write a value here with a non-zero high bit, prepare to start playing */
  1250.     stream_update(dac_stream, 0);
  1251.     if (!(data & 0x80) && ym2151.active_timer != 2)
  1252.     {
  1253.         dac.invalid = 1;
  1254.         timer_set(TIME_IN_MSEC(1), 0, dac_start);
  1255.     }
  1256.  
  1257.     dac.state_bank[offset] = data;
  1258. }
  1259.  
  1260.  
  1261. /***************************************************************************
  1262.     SOUND GENERATION
  1263. ****************************************************************************/
  1264.  
  1265. static void cvsd_update(int num, INT16 *buffer, int length)
  1266. {
  1267.     UINT8 *bank_base, *source, *end;
  1268.     UINT32 current;
  1269.     int i;
  1270.  
  1271.     /* CVSD generation */
  1272.     if (cvsd.state && !(cvsd.state[0] & 0x80))
  1273.     {
  1274.         UINT8 bits_left = cvsd.state[0];
  1275.         UINT8 current_byte = cvsd.state[1];
  1276.  
  1277.         /* determine start and end points */
  1278.         bank_base = get_cvsd_bank_base(cvsd.bank[0]) - 0x8000;
  1279.         source = bank_base + get_cvsd_address();
  1280.         end = bank_base + cvsd.end[0] * 256 + cvsd.end[1];
  1281.  
  1282.         current = cvsd.sample_position;
  1283.  
  1284.         /* fill in with samples until we hit the end or run out */
  1285.         for (i = 0; i < length; i++)
  1286.         {
  1287.             /* if we overflow to the next sample, process it */
  1288.             while (current > 0xffff)
  1289.             {
  1290.                 if (bits_left-- == 0)
  1291.                 {
  1292.                     if (source >= end)
  1293.                     {
  1294.                         bits_left |= 0x80;
  1295.                         cvsd.sample_position = 0x10000;
  1296.                         cvsd.integrator = 0;
  1297.                         cvsd.filter = FILTER_MIN;
  1298.                         cvsd.shiftreg = 0xaa;
  1299.                         memset(buffer, 0, (length - i) * sizeof(INT16));
  1300.                         goto finished;
  1301.                     }
  1302.                     current_byte = *source++;
  1303.                     bits_left = 7;
  1304.                 }
  1305.                 cvsd.current_sample = get_next_cvsd_sample(current_byte & (0x80 >> bits_left));
  1306.                 current -= 0x10000;
  1307.             }
  1308.  
  1309.             *buffer++ = cvsd.current_sample;
  1310.             current += cvsd.sample_step;
  1311.         }
  1312.  
  1313.         /* update the final values */
  1314.     finished:
  1315.         set_cvsd_address(source - bank_base);
  1316.         cvsd.sample_position = current;
  1317.         cvsd.state[0] = bits_left;
  1318.         cvsd.state[1] = current_byte;
  1319.     }
  1320.     else
  1321.         memset(buffer, 0, length * sizeof(INT16));
  1322. }
  1323.  
  1324.  
  1325. static void dac_update(int num, INT16 *buffer, int length)
  1326. {
  1327.     UINT8 *bank_base, *source, *end;
  1328.     UINT32 current;
  1329.     int i;
  1330.  
  1331.     /* DAC generation */
  1332.     if (dac.state_bank && !(dac.state_bank[0] & 0x80))
  1333.     {
  1334.         UINT8 volume = dac.volume[0] / 4;
  1335.  
  1336.         /* determine start and end points */
  1337.         if (williams_audio_type == WILLIAMS_CVSD)
  1338.             bank_base = get_cvsd_bank_base(dac.state_bank[0]) - 0x8000;
  1339.         else if (williams_audio_type == WILLIAMS_ADPCM)
  1340.             bank_base = get_adpcm_bank_base(dac.state_bank[0]) - 0x4000;
  1341.         else
  1342.             bank_base = get_narc_master_bank_base(dac.state_bank[0]) - 0x4000;
  1343.         source = bank_base + get_dac_address();
  1344.         end = bank_base + dac.end[0] * 256 + dac.end[1];
  1345.  
  1346.         current = dac.sample_position;
  1347.  
  1348.         /* fill in with samples until we hit the end or run out */
  1349.         for (i = 0; i < length; i++)
  1350.         {
  1351.             /* if we overflow to the next sample, process it */
  1352.             while (current > 0xffff)
  1353.             {
  1354.                 if (source >= end)
  1355.                 {
  1356.                     dac.state_bank[0] |= 0x80;
  1357.                     dac.sample_position = 0x10000;
  1358.                     memset(buffer, 0, (length - i) * sizeof(INT16));
  1359.                     goto finished;
  1360.                 }
  1361.                 dac.current_sample = *source++ * volume;
  1362.                 current -= 0x10000;
  1363.             }
  1364.  
  1365.             *buffer++ = dac.current_sample;
  1366.             current += dac.sample_step;
  1367.         }
  1368.  
  1369.         /* update the final values */
  1370.     finished:
  1371.         set_dac_address(source - bank_base);
  1372.         dac.sample_position = current;
  1373.     }
  1374.     else
  1375.         memset(buffer, 0, length * sizeof(INT16));
  1376. }
  1377.  
  1378.  
  1379. /***************************************************************************
  1380.     CVSD DECODING (cribbed from HC55516.c)
  1381. ****************************************************************************/
  1382.  
  1383. INT16 get_next_cvsd_sample(int bit)
  1384. {
  1385.     double temp;
  1386.  
  1387.     /* move the estimator up or down a step based on the bit */
  1388.     if (bit)
  1389.     {
  1390.         cvsd.shiftreg = ((cvsd.shiftreg << 1) | 1) & 7;
  1391.         cvsd.integrator += cvsd.filter;
  1392.     }
  1393.     else
  1394.     {
  1395.         cvsd.shiftreg = (cvsd.shiftreg << 1) & 7;
  1396.         cvsd.integrator -= cvsd.filter;
  1397.     }
  1398.  
  1399.     /* simulate leakage */
  1400.     cvsd.integrator *= cvsd.leak;
  1401.  
  1402.     /* if we got all 0's or all 1's in the last n bits, bump the step up */
  1403.     if (cvsd.shiftreg == 0 || cvsd.shiftreg == 7)
  1404.     {
  1405.         cvsd.filter = FILTER_MAX - ((FILTER_MAX - cvsd.filter) * cvsd.charge);
  1406.         if (cvsd.filter > FILTER_MAX)
  1407.             cvsd.filter = FILTER_MAX;
  1408.     }
  1409.  
  1410.     /* simulate decay */
  1411.     else
  1412.     {
  1413.         cvsd.filter *= cvsd.decay;
  1414.         if (cvsd.filter < FILTER_MIN)
  1415.             cvsd.filter = FILTER_MIN;
  1416.     }
  1417.  
  1418.     /* compute the sample as a 32-bit word */
  1419.     temp = cvsd.integrator * SAMPLE_GAIN;
  1420.  
  1421.     /* compress the sample range to fit better in a 16-bit word */
  1422.     if (temp < 0)
  1423.         return (int)(temp / (-temp * (1.0 / 32768.0) + 1.0));
  1424.     else
  1425.         return (int)(temp / (temp * (1.0 / 32768.0) + 1.0));
  1426. }
  1427.